home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / decprom / fsDisk.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-31  |  16.5 KB  |  524 lines

  1. /* 
  2.  * fsDisk.c --
  3.  *
  4.  *    Routines related to managing local disks.  Each partition of a local
  5.  *    disk (partitions are defined by a table on the disk header) is
  6.  *    called a ``domain''.  FsAttachDisk attaches a domain into the file
  7.  *    system, and FsDeattachDisk removes it.  A domain is given
  8.  *    a number the first time it is ever attached.  This is recorded on
  9.  *    the disk so it doesn't change between boots.  The domain number is
  10.  *    used to identify disks, and a domain number plus a file number is
  11.  *    used to identify files.  Fsdm_DomainFetch is used to get the state
  12.  *    associated with a disk, and Fsdm_DomainRelease releases the reference
  13.  *    on the state.  FsDetachDisk checks the references on domains in
  14.  *    the normal (non-forced) case so that active disks aren't detached.
  15.  *
  16.  * Copyright 1987 Regents of the University of California
  17.  * All rights reserved.
  18.  * Permission to use, copy, modify, and distribute this
  19.  * software and its documentation for any purpose and without
  20.  * fee is hereby granted, provided that the above copyright
  21.  * notice appear in all copies.  The University of California
  22.  * makes no representations about the suitability of this
  23.  * software for any purpose.  It is provided "as is" without
  24.  * express or implied warranty.
  25.  */
  26.  
  27. #ifdef notdef
  28. static char rcsid[] = "$Header: /sprite/src/boot/decprom/RCS/fsDisk.c,v 1.2 91/08/30 17:36:16 shirriff Exp $ SPRITE (Berkeley)";
  29. #endif not lint
  30.  
  31.  
  32. #include "sprite.h"
  33.  
  34. #include "fsBoot.h"
  35. #include "kernel/devDiskLabel.h"
  36. #include "kernel/dev.h"
  37. #include "kernel/devFsOpTable.h"
  38. #include "kernel/machMon.h"
  39. #include "kernel/ofs.h"
  40.  
  41. #define NO_PRINTF
  42. /*
  43.  * fsDevice is copied into all Fsio_FileIOHandles.  It is used by the drivers
  44.  * to get to the partition and geometry information for the disk.
  45.  */
  46. Fs_Device fsDevice;
  47.  
  48. /*
  49.  * fsDomainPtr and fsRootHandlePtr are used by Fs_Open.
  50.  */
  51. static Fsdm_Domain fsDomain;
  52. Fsdm_Domain *fsDomainPtr = &fsDomain;
  53. static Fsio_FileIOHandle fsRootHandle;
  54. Fsio_FileIOHandle *fsRootHandlePtr = &fsRootHandle;
  55.  
  56. /*
  57.  * Forward declarations.
  58.  */
  59. static int    InstallLocalDomain();
  60. void        AddDomainFlags();
  61. static Boolean    IsDecLabel();
  62.  
  63. /*
  64.  *----------------------------------------------------------------------
  65.  *
  66.  * FsAttachDisk --
  67.  *
  68.  *    Make a particular local disk partition correspond to a prefix.
  69.  *    This makes sure the disk is up, reads the domain header,
  70.  *    and calls the initialization routine for the block I/O module
  71.  *    of the disk's driver.  By the time this is called the device
  72.  *    initialization routines have already been called from Dev_Config
  73.  *    so the device driver knows how the disk is partitioned into
  74.  *    domains.  This routine sees if the domain is formatted correctly,
  75.  *    and if so attaches it to the set of domains.
  76.  *
  77.  * Results:
  78.  *    SUCCESS if the disk was readable and had a good domain header.
  79.  *
  80.  * Side effects:
  81.  *    Sets up the Fsdm_DomainInfo for the domain.
  82.  *
  83.  *----------------------------------------------------------------------
  84.  */
  85. ReturnStatus
  86. FsAttachDisk(fsDevicePtr)
  87.     Fs_Device *fsDevicePtr;        /* Global FS device descriptor */
  88. {
  89.     ReturnStatus status;        /* Error code */
  90.     register Address buffer;        /* Read buffer */
  91.     int headerSector;            /* Starting sector of domain header */
  92.     int numHeaderSectors;        /* Number of sectors in domain header */
  93.     int summarySector;            /* Sector of summary information. */
  94.     Ofs_SummaryInfo *summaryInfoPtr;    /* Pointer to summary info. */
  95.     int amountRead;            /* Returned from read call */
  96.     int devType;            /* Device type index */
  97.  
  98.     /*
  99.      * Open the raw disk device so we can grub around in the header info.
  100.      */
  101. #ifndef NO_PRINTF
  102.     Mach_MonPrintf("FsAttachDisk: ptr = %x\n", fsDevicePtr);
  103. #endif
  104.     devType = DEV_TYPE_INDEX(fsDevicePtr->type);
  105. #ifndef NO_PRINTF
  106.     Mach_MonPrintf("Jumping to 0x%x (%d)\n", devFsOpTable[devType].open,
  107.     devType);
  108. #endif
  109.     status = (*devFsOpTable[devType].open)(&fsDevice);
  110.     if (status != SUCCESS) {
  111.     Mach_MonPrintf("Failure\n");
  112.     return(status);
  113.     }
  114. #ifndef NO_PRINTF
  115.     Mach_MonPrintf("Mallocing\n");
  116. #endif
  117.     buffer = (Address)malloc(DEV_BYTES_PER_SECTOR);
  118. #ifndef NO_PRINTF
  119.     Mach_MonPrintf("Done mallocing\n");
  120. #endif
  121.  
  122.     /*
  123.      * Read the 31st sector of the partition.  It has a copy of the
  124.      * 31st sector of the whole disk which describes how the rest of the
  125.      * domain's zero'th cylinder is layed out.
  126.      */
  127.     status = (*devFsOpTable[devType].read)(&fsDevice,
  128.         DEC_LABEL_SECTOR*DEV_BYTES_PER_SECTOR,
  129.         DEV_BYTES_PER_SECTOR, buffer, &amountRead);
  130.     if (status != SUCCESS) {
  131. #ifndef NO_PRINTF
  132.     Mach_MonPrintf("label (sector 31) read fail\n");
  133. #endif
  134.     return(status);
  135.     }
  136. #ifndef NO_PRINTF
  137.     Mach_MonPrintf("Checking format\n");
  138. #endif
  139.     /*
  140.      * Check for different disk formats, and figure out how the rest
  141.      * of the zero'th cylinder is layed out.
  142.      */
  143.     if (((Dec_DiskLabel *)buffer)->magic != DEC_LABEL_MAGIC) {
  144. #ifndef NO_PRINTF
  145.     Mach_MonPrintf("Bad magic <%x>\n", ((Dec_DiskLabel *)buffer)->magic);
  146. #endif
  147.     }
  148.  
  149.     headerSector = ((Dec_DiskLabel *)buffer)->domainSector;
  150.     numHeaderSectors = ((Dec_DiskLabel *)buffer)->numDomainSectors;
  151.     /*
  152.      * Read the domain header and save it with the domain state.
  153.      */
  154.     buffer = (Address)malloc(DEV_BYTES_PER_SECTOR * numHeaderSectors);
  155.     status = (*devFsOpTable[devType].read)(&fsDevice,
  156.         headerSector * DEV_BYTES_PER_SECTOR,
  157.         numHeaderSectors * DEV_BYTES_PER_SECTOR,
  158.         buffer, &amountRead);
  159. #ifndef NO_PRINTF
  160.     Mach_MonPrintf("Read header\n");
  161. #endif
  162.     if (status != SUCCESS) {
  163. #ifndef NO_PRINTF
  164.     Mach_MonPrintf("Domain fail\n");
  165. #endif
  166.     return(status);
  167.     } else if (((Ofs_DomainHeader *)buffer)->magic != OFS_DOMAIN_MAGIC) {
  168. #ifndef NO_PRINTF
  169.     Mach_MonPrintf("Bad magic <%x>\n",
  170.         ((Ofs_DomainHeader *)buffer)->magic);
  171. #endif
  172.     return(FAILURE);
  173.     }
  174.  
  175.     fsDomainPtr->headerPtr = (Ofs_DomainHeader *) buffer;
  176.  
  177.      /*
  178.      * Set up the ClientData part of *devicePtr to reference the
  179.      * Ofs_Geometry part of the domain header.  This is used by the
  180.      * block I/O routines.
  181.      */
  182.     fsDevicePtr->data = (ClientData)&fsDomainPtr->headerPtr->geometry;
  183.  
  184.     /*
  185.      * Set up a file handle for the root directory.  What is important
  186.      * is the device info (for Block IO) and the file descriptor itself.
  187.      */
  188. #ifndef NO_PRINTF
  189.     Mach_MonPrintf("Init'ing handle\n");
  190. #endif
  191.     FsInitFileHandle(fsDomainPtr, FSDM_ROOT_FILE_NUMBER, fsRootHandlePtr);
  192. #ifndef NO_PRINTF
  193.     Mach_MonPrintf("Done\n");
  194. #endif
  195.     return(SUCCESS);
  196. }
  197.  
  198.  
  199. /*
  200.  *----------------------------------------------------------------------
  201.  *
  202.  * IsSunLabel --
  203.  *
  204.  *    Poke around in the input buffer and see if it looks like
  205.  *    a Sun format disk label.
  206.  *
  207.  * Results:
  208.  *    TRUE or FALSE
  209.  *
  210.  * Side effects:
  211.  *    None.
  212.  *
  213.  *----------------------------------------------------------------------
  214.  */
  215. #ifdef notdef
  216. static Boolean
  217. IsSunLabel(buffer)
  218.     Address buffer;    /* Buffer containing zero'th sector */
  219. {
  220.     register Sun_DiskLabel *sunLabelPtr;
  221.  
  222.     sunLabelPtr = (Sun_DiskLabel *)buffer;
  223.     if (sunLabelPtr->magic == SUN_DISK_MAGIC) {
  224.     /*
  225.      * Should check checkSum...
  226.      */
  227.     return(TRUE);
  228.     } else {
  229.     return(FALSE);
  230.     }
  231. }
  232. #endif
  233.  
  234. /*
  235.  *----------------------------------------------------------------------
  236.  *
  237.  * IsSpriteLabel --
  238.  *
  239.  *    Poke around in the input buffer and see if it looks like
  240.  *    a Sprite format disk header.
  241.  *
  242.  * Results:
  243.  *    TRUE or FALSE
  244.  *
  245.  * Side effects:
  246.  *    None.
  247.  *
  248.  *----------------------------------------------------------------------
  249.  */
  250. #ifdef notdef
  251. static Boolean
  252. IsSpriteLabel(buffer)
  253.     Address buffer;    /* Buffer containing zero'th sector */
  254. {
  255.     register FsDiskHeader *diskHeaderPtr;
  256.     register int index;
  257.     register int checkSum;
  258.  
  259.     diskHeaderPtr = (FsDiskHeader *)buffer;
  260.     if (diskHeaderPtr->magic == FSDM_DISK_MAGIC) {
  261.         return(TRUE);
  262.     }
  263.     }
  264.     return(FALSE);
  265. }
  266. #endif
  267.  
  268. /*
  269.  *----------------------------------------------------------------------
  270.  * The following routines are used by device drivers to map from block
  271.  * and sector numbers to disk addresses.  There are two sets, one for
  272.  * drivers that use logical sector numbers (i.e. SCSI) and the other
  273.  * for <cyl,head,sector> format disk addresses.
  274.  *----------------------------------------------------------------------
  275.  */
  276.  
  277. /*
  278.  *----------------------------------------------------------------------
  279.  *
  280.  * Fs_BlocksToSectors --
  281.  *
  282.  *    Convert from block indexes (actually, fragment indexes) to
  283.  *    sectors using the geometry information on the disk.  This
  284.  *    is a utility for block device drivers.
  285.  *
  286.  * Results:
  287.  *    The sector number that corresponds to the fragment index.
  288.  *    The caller has to make sure that its I/O doesn't cross a
  289.  *    filesystem block boundary.
  290.  *
  291.  * Side effects:
  292.  *    None.
  293.  *
  294.  *----------------------------------------------------------------------
  295.  */
  296. #define SECTORS_PER_FRAG    (FS_FRAGMENT_SIZE / DEV_BYTES_PER_SECTOR)
  297. #if defined(SCSI_DISK_BOOT) || defined(SUN_PROM_BOOT)
  298. int
  299. Fs_BlocksToSectors(fragNumber, data)
  300.     int fragNumber;    /* Fragment index to map into block index */
  301.     ClientData data;    /* ClientData from the device info */
  302. {
  303.     register Ofs_Geometry *geoPtr;
  304.     register int sectorNumber;    /* The sector corresponding to the fragment */
  305.     register int cylinder;    /* The cylinder number of the fragment */
  306.     register int rotationalSet;    /* The rotational set with cylinder of frag */
  307.     register int blockNumber;    /* The block number within rotational set */
  308.  
  309.     geoPtr         = (Ofs_Geometry *)data;
  310.     blockNumber        = fragNumber / FS_FRAGMENTS_PER_BLOCK;
  311.     cylinder        = blockNumber / geoPtr->blocksPerCylinder;
  312.     if (geoPtr->rotSetsPerCyl > 0) {
  313.     /*
  314.      * Do fancy rotational set mapping.
  315.      */
  316.     blockNumber        -= cylinder * geoPtr->blocksPerCylinder;
  317.     rotationalSet    = blockNumber / geoPtr->blocksPerRotSet;
  318.     blockNumber        -= rotationalSet * geoPtr->blocksPerRotSet;
  319.  
  320.     sectorNumber = geoPtr->sectorsPerTrack * geoPtr->numHeads * cylinder +
  321.               geoPtr->sectorsPerTrack * geoPtr->tracksPerRotSet *
  322.               rotationalSet +
  323.               geoPtr->blockOffset[blockNumber];
  324.     sectorNumber += (fragNumber % FS_FRAGMENTS_PER_BLOCK) * SECTORS_PER_FRAG;
  325.     } else {
  326.     /*
  327.      * Do straight-forward mapping.
  328.      */
  329.     sectorNumber = geoPtr->sectorsPerTrack * geoPtr->numHeads * cylinder +
  330.             fragNumber * SECTORS_PER_FRAG - cylinder * 
  331.             geoPtr->blocksPerCylinder * FS_FRAGMENTS_PER_BLOCK *
  332.             SECTORS_PER_FRAG;
  333.     }
  334.  
  335.     return(sectorNumber);
  336. }
  337. #endif
  338.  
  339. /*
  340.  *----------------------------------------------------------------------
  341.  *
  342.  * Fs_BlocksToDiskAddr --
  343.  *
  344.  *    Convert from block indexes (actually, fragment indexes) to
  345.  *    disk address (head, cylinder, sector) using the geometry information
  346.  *     on the disk.  This is a utility for block device drivers.
  347.  *
  348.  * Results:
  349.  *    The disk address that corresponds to the disk address.
  350.  *    The caller has to make sure that its I/O doesn't cross a
  351.  *    filesystem block boundary.
  352.  *
  353.  * Side effects:
  354.  *    None.
  355.  *
  356.  *----------------------------------------------------------------------
  357.  */
  358. #ifdef XYLOGICS_BOOT
  359. void
  360. Fs_BlocksToDiskAddr(fragNumber, data, diskAddrPtr)
  361.     int fragNumber;    /* Fragment index to map into block index */
  362.     ClientData data;    /* ClientData from the device info */
  363.     Dev_DiskAddr *diskAddrPtr;
  364. {
  365.     register Ofs_Geometry *geoPtr;
  366.     register int sectorNumber;    /* The sector corresponding to the fragment */
  367.     register int cylinder;    /* The cylinder number of the fragment */
  368.     register int rotationalSet;    /* The rotational set with cylinder of frag */
  369.     register int blockNumber;    /* The block number within rotational set */
  370.  
  371.     geoPtr         = (Ofs_Geometry *)data;
  372.     /*
  373.      * Map to block number because the rotational sets are laid out
  374.      * relative to blocks.  After that the cylinder is easy because we know
  375.      * blocksPerCylinder.  To get the head and sector we first get the
  376.      * rotational set (described in fsDisk.h) of the block and the
  377.      * block's sector offset (relative to the rotational set!).  This complex
  378.      * algorithm crops up because there isn't necessarily an even number
  379.      * of blocks per track.  The 'blockOffset' array in the geometry gives
  380.      * a sector index of each successive block in a rotational set. Finally,
  381.      * we can use the sectorsPerTrack to get the head and sector.
  382.      */
  383.     blockNumber        = fragNumber / FS_FRAGMENTS_PER_BLOCK;
  384.     cylinder        = blockNumber / geoPtr->blocksPerCylinder;
  385.     blockNumber        -= cylinder * geoPtr->blocksPerCylinder;
  386.     diskAddrPtr->cylinder = cylinder;
  387.  
  388.     rotationalSet    = blockNumber / geoPtr->blocksPerRotSet;
  389.     blockNumber        -= rotationalSet * geoPtr->blocksPerRotSet;
  390. /*
  391.  * The follow statment had to be broken into two because the compiler used
  392.  * register d2 to do the modulo operation, but wasn't saving its value.
  393.  */
  394.     sectorNumber    = geoPtr->sectorsPerTrack * geoPtr->tracksPerRotSet *
  395.               rotationalSet + geoPtr->blockOffset[blockNumber];
  396.     sectorNumber    +=
  397.             (fragNumber % FS_FRAGMENTS_PER_BLOCK) * SECTORS_PER_FRAG;
  398.  
  399.     diskAddrPtr->head    = sectorNumber / geoPtr->sectorsPerTrack;
  400.     diskAddrPtr->sector = sectorNumber -
  401.               diskAddrPtr->head * geoPtr->sectorsPerTrack;
  402. }
  403. #endif
  404.  
  405. /*
  406.  *----------------------------------------------------------------------
  407.  *
  408.  * Fs_SectorsToRawDiskAddr --
  409.  *
  410.  *      Convert from a sector offset to a raw disk address (cyl, head,
  411.  *      sector) using the geometry information on the disk.  This is a
  412.  *      utility for raw device drivers and does not pay attention to the
  413.  *      rotational position of filesystem disk blocks.
  414.  *
  415.  *    This should be moved to Dev
  416.  *
  417.  * Results:
  418.  *    The disk address that corresponds exactly to the byte offset.
  419.  *
  420.  * Side effects:
  421.  *    None.
  422.  *
  423.  *----------------------------------------------------------------------
  424.  */
  425. #ifdef XYLOGICS_BOOT
  426. int
  427. Fs_SectorsToRawDiskAddr(sector, numSectors, numHeads, diskAddrPtr)
  428.     int sector;        /* Sector number (counting from zero 'til the total
  429.              * number of sectors in the disk) */
  430.     int numSectors;    /* Number of sectors per track */
  431.     int numHeads;    /* Number of heads on the disk */
  432.     Dev_DiskAddr *diskAddrPtr;
  433. {
  434.     register int sectorsPerCyl;    /* The rotational set with cylinder of frag */
  435.  
  436.     sectorsPerCyl        = numSectors * numHeads;
  437.     diskAddrPtr->cylinder    = sector / sectorsPerCyl;
  438.     sector            -= diskAddrPtr->cylinder * sectorsPerCyl;
  439.     diskAddrPtr->head        = sector / numSectors;
  440.     diskAddrPtr->sector        = sector - numSectors * diskAddrPtr->head;
  441. }
  442. #endif
  443.  
  444.  
  445. /*
  446.  *----------------------------------------------------------------------
  447.  *
  448.  * FsDeviceBlockIO --
  449.  *
  450.  *    Map a file system block address to a block device block address 
  451.  *    perform the requested operation.
  452.  *
  453.  * NOTE: This routine is temporary and should be replaced when the file system
  454.  *     is converted to use the async block io interface.
  455.  *
  456.  * Results:
  457.  *    The return status of the operation.
  458.  *
  459.  * Side effects:
  460.  *    Blocks may be written or read.
  461.  *
  462.  *----------------------------------------------------------------------
  463.  */
  464.  
  465. ReturnStatus
  466. FsDeviceBlockIO(readWriteFlag, devicePtr, fragNumber, numFrags, buffer)
  467.     int readWriteFlag;        /* FS_READ or FS_WRITE */
  468.     Fs_Device *devicePtr;    /* Specifies device type to do I/O with */
  469.     int fragNumber;        /* CAREFUL, fragment index, not block index.
  470.                  * This is relative to start of device. */
  471.     int numFrags;        /* CAREFUL, number of fragments, not blocks */
  472.     Address buffer;        /* I/O buffer */
  473. {
  474.     ReturnStatus status;    /* General return code */
  475.     int firstSector;        /* Starting sector of transfer */
  476.     DevBlockDeviceRequest    request;
  477.     int                transferCount;
  478.     int                devType;
  479.  
  480.     devType = DEV_TYPE_INDEX(devicePtr->type);
  481.     if ((fragNumber % FS_FRAGMENTS_PER_BLOCK) != 0) {
  482.     /*
  483.      * The I/O doesn't start on a block boundary.  Transfer the
  484.      * first few extra fragments to get things going on a block boundary.
  485.      */
  486.     register int extraFrags;
  487.  
  488.     extraFrags = FS_FRAGMENTS_PER_BLOCK -
  489.             (fragNumber % FS_FRAGMENTS_PER_BLOCK);
  490.     if (extraFrags > numFrags) {
  491.         extraFrags = numFrags;
  492.     }
  493.     firstSector = Fs_BlocksToSectors(fragNumber, devicePtr->data);
  494.     status = (*devFsOpTable[devType].read)(devicePtr,
  495.         firstSector * DEV_BYTES_PER_SECTOR,
  496.         extraFrags * FS_FRAGMENT_SIZE, buffer, &transferCount);
  497.     if (status != SUCCESS) {
  498. #ifndef NO_PRINTF
  499.         Mach_MonPrintf("Fragment read failure\n");
  500. #endif
  501.     }
  502.     extraFrags = transferCount / FS_FRAGMENT_SIZE;
  503.     fragNumber += extraFrags;
  504.     buffer += transferCount;
  505.     numFrags -= extraFrags;
  506.     }
  507.     if (numFrags > 0) {
  508.     /*
  509.      * Transfer the left over fragments.
  510.      */
  511.     firstSector = Fs_BlocksToSectors(fragNumber, devicePtr->data);
  512.     status = (*devFsOpTable[devType].read)(devicePtr,
  513.         firstSector * DEV_BYTES_PER_SECTOR,
  514.         numFrags * FS_FRAGMENT_SIZE, buffer, &transferCount);
  515.     if (status != SUCCESS) {
  516. #ifndef NO_PRINTF
  517.         Mach_MonPrintf("Last fragment read failure\n");
  518. #endif
  519.     }
  520.     }
  521.     return(status);
  522. }
  523.  
  524.